package oss

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/user/go-capcut/internal/config"
)

// OSSClient OSS客户端接口
type OSSClient interface {
	UploadFile(localFilePath, objectKey string) (string, error)
	UploadData(data []byte, objectKey string) (string, error)
	DownloadFile(objectKey, localFilePath string) error
	GetObjectURL(objectKey string) string
	DeleteObject(objectKey string) error
}

// AliyunOSSClient 阿里云OSS客户端
type AliyunOSSClient struct {
	Client     *oss.Client
	Bucket     *oss.Bucket
	BucketName string
	Endpoint   string
}

// NewAliyunOSSClient 创建新的阿里云OSS客户端
func NewAliyunOSSClient(cfg *config.Config) (*AliyunOSSClient, error) {
	// 创建OSS客户端
	client, err := oss.New(cfg.OssConfig.Endpoint, cfg.OssConfig.AccessKeyID, cfg.OssConfig.AccessKeySecret)
	if err != nil {
		return nil, fmt.Errorf("创建OSS客户端失败: %w", err)
	}

	// 获取存储空间
	bucket, err := client.Bucket(cfg.OssConfig.BucketName)
	if err != nil {
		return nil, fmt.Errorf("获取存储空间失败: %w", err)
	}

	return &AliyunOSSClient{
		Client:     client,
		Bucket:     bucket,
		BucketName: cfg.OssConfig.BucketName,
		Endpoint:   cfg.OssConfig.Endpoint,
	}, nil
}

// UploadFile 上传文件
func (c *AliyunOSSClient) UploadFile(localFilePath, objectKey string) (string, error) {
	// 上传文件
	err := c.Bucket.PutObjectFromFile(objectKey, localFilePath)
	if err != nil {
		return "", fmt.Errorf("上传文件失败: %w", err)
	}

	// 返回文件URL
	return c.GetObjectURL(objectKey), nil
}

// UploadData 上传数据
func (c *AliyunOSSClient) UploadData(data []byte, objectKey string) (string, error) {
	// 上传数据
	err := c.Bucket.PutObject(objectKey, bytes.NewReader(data))
	if err != nil {
		return "", fmt.Errorf("上传数据失败: %w", err)
	}

	// 返回文件URL
	return c.GetObjectURL(objectKey), nil
}

// DownloadFile 下载文件
func (c *AliyunOSSClient) DownloadFile(objectKey, localFilePath string) error {
	// 创建目录
	dir := filepath.Dir(localFilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建目录失败: %w", err)
	}

	// 下载文件
	return c.Bucket.GetObjectToFile(objectKey, localFilePath)
}

// GetObjectURL 获取对象URL
func (c *AliyunOSSClient) GetObjectURL(objectKey string) string {
	// 构建URL
	endpoint := c.Endpoint
	if strings.HasPrefix(endpoint, "http://") {
		endpoint = endpoint[7:]
	} else if strings.HasPrefix(endpoint, "https://") {
		endpoint = endpoint[8:]
	}

	return fmt.Sprintf("https://%s.%s/%s", c.BucketName, endpoint, objectKey)
}

// DeleteObject 删除对象
func (c *AliyunOSSClient) DeleteObject(objectKey string) error {
	return c.Bucket.DeleteObject(objectKey)
}

// LocalOSSClient 本地文件系统模拟的OSS客户端
type LocalOSSClient struct {
	BaseDir   string
	BaseURL   string
	BucketDir string
}

// NewLocalOSSClient 创建新的本地OSS客户端
func NewLocalOSSClient(baseDir, baseURL, bucketName string) (*LocalOSSClient, error) {
	// 创建存储目录
	bucketDir := filepath.Join(baseDir, bucketName)
	if err := os.MkdirAll(bucketDir, 0755); err != nil {
		return nil, fmt.Errorf("创建存储目录失败: %w", err)
	}

	return &LocalOSSClient{
		BaseDir:   baseDir,
		BaseURL:   baseURL,
		BucketDir: bucketDir,
	}, nil
}

// UploadFile 上传文件
func (c *LocalOSSClient) UploadFile(localFilePath, objectKey string) (string, error) {
	// 目标文件路径
	dstPath := filepath.Join(c.BucketDir, objectKey)

	// 创建目录
	dir := filepath.Dir(dstPath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", fmt.Errorf("创建目录失败: %w", err)
	}

	// 复制文件
	src, err := os.Open(localFilePath)
	if err != nil {
		return "", fmt.Errorf("打开源文件失败: %w", err)
	}
	defer src.Close()

	dst, err := os.Create(dstPath)
	if err != nil {
		return "", fmt.Errorf("创建目标文件失败: %w", err)
	}
	defer dst.Close()

	if _, err := io.Copy(dst, src); err != nil {
		return "", fmt.Errorf("复制文件失败: %w", err)
	}

	// 返回文件URL
	return c.GetObjectURL(objectKey), nil
}

// UploadData 上传数据
func (c *LocalOSSClient) UploadData(data []byte, objectKey string) (string, error) {
	// 目标文件路径
	dstPath := filepath.Join(c.BucketDir, objectKey)

	// 创建目录
	dir := filepath.Dir(dstPath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", fmt.Errorf("创建目录失败: %w", err)
	}

	// 写入文件
	if err := os.WriteFile(dstPath, data, 0644); err != nil {
		return "", fmt.Errorf("写入文件失败: %w", err)
	}

	// 返回文件URL
	return c.GetObjectURL(objectKey), nil
}

// DownloadFile 下载文件
func (c *LocalOSSClient) DownloadFile(objectKey, localFilePath string) error {
	// 源文件路径
	srcPath := filepath.Join(c.BucketDir, objectKey)

	// 创建目录
	dir := filepath.Dir(localFilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建目录失败: %w", err)
	}

	// 复制文件
	src, err := os.Open(srcPath)
	if err != nil {
		return fmt.Errorf("打开源文件失败: %w", err)
	}
	defer src.Close()

	dst, err := os.Create(localFilePath)
	if err != nil {
		return fmt.Errorf("创建目标文件失败: %w", err)
	}
	defer dst.Close()

	if _, err := io.Copy(dst, src); err != nil {
		return fmt.Errorf("复制文件失败: %w", err)
	}

	return nil
}

// GetObjectURL 获取对象URL
func (c *LocalOSSClient) GetObjectURL(objectKey string) string {
	return fmt.Sprintf("%s/%s", c.BaseURL, objectKey)
}

// DeleteObject 删除对象
func (c *LocalOSSClient) DeleteObject(objectKey string) error {
	// 文件路径
	filePath := filepath.Join(c.BucketDir, objectKey)

	// 删除文件
	return os.Remove(filePath)
}
